package com.loren.tetris.data.entity;

import com.loren.tetris.data.constant.DataConstant;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class BlockShape {

    private final boolean rotate;

    private final List<Block> blockList;

    private static final Random RANDOM = new Random();

    public BlockShape(boolean rotate, List<Block> blockList) {
        this.rotate = rotate;
        this.blockList = blockList;
    }

    public List<Block> getBlockList() {
        return blockList;
    }

    /**
     * 左7形状
     */
    private static BlockShape blockShapeLeft7() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_PURPLE));
        blocks.add(new Block(3, -3, DataConstant.COLOR_PURPLE));
        blocks.add(new Block(4, -3, DataConstant.COLOR_PURPLE));
        blocks.add(new Block(4, -1, DataConstant.COLOR_PURPLE));
        return new BlockShape(true, blocks);
    }

    /**
     * 右7形状
     */
    private static BlockShape blockShapeRight7() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_BLUE));
        blocks.add(new Block(4, -3, DataConstant.COLOR_BLUE));
        blocks.add(new Block(5, -3, DataConstant.COLOR_BLUE));
        blocks.add(new Block(4, -1, DataConstant.COLOR_BLUE));
        return new BlockShape(true, blocks);
    }

    /**
     * 左Z形状
     */
    private static BlockShape blockShapeLeftZ() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_CYAN));
        blocks.add(new Block(3, -3, DataConstant.COLOR_CYAN));
        blocks.add(new Block(3, -2, DataConstant.COLOR_CYAN));
        blocks.add(new Block(4, -1, DataConstant.COLOR_CYAN));
        return new BlockShape(true, blocks);
    }

    /**
     * 右Z形状
     */
    private static BlockShape blockShapeRightZ() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_GREEN));
        blocks.add(new Block(5, -2, DataConstant.COLOR_GREEN));
        blocks.add(new Block(5, -3, DataConstant.COLOR_GREEN));
        blocks.add(new Block(4, -1, DataConstant.COLOR_GREEN));
        return new BlockShape(true, blocks);
    }

    /**
     * 方块形状
     */
    private static BlockShape blockShapeBlock() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(3, -2, DataConstant.COLOR_YELLOW));
        blocks.add(new Block(4, -2, DataConstant.COLOR_YELLOW));
        blocks.add(new Block(3, -1, DataConstant.COLOR_YELLOW));
        blocks.add(new Block(4, -1, DataConstant.COLOR_YELLOW));
        return new BlockShape(false, blocks);
    }

    /**
     * T字形状
     */
    private static BlockShape blockShapeT() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_ORANGE));
        blocks.add(new Block(3, -2, DataConstant.COLOR_ORANGE));
        blocks.add(new Block(5, -2, DataConstant.COLOR_ORANGE));
        blocks.add(new Block(4, -1, DataConstant.COLOR_ORANGE));
        return new BlockShape(true, blocks);
    }

    /**
     * 长条形状
     */
    private static BlockShape blockShapeLine() {
        List<Block> blocks = new ArrayList<>();
        blocks.add(new Block(4, -2, DataConstant.COLOR_RED));
        blocks.add(new Block(4, -4, DataConstant.COLOR_RED));
        blocks.add(new Block(4, -3, DataConstant.COLOR_RED));
        blocks.add(new Block(4, -1, DataConstant.COLOR_RED));
        return new BlockShape(true, blocks);
    }

    /**
     * 随机方块形状
     */
    public static BlockShape blockShapeRandom() {
        List<BlockShape> blockShapeList = new ArrayList<>();
        blockShapeList.add(BlockShape.blockShapeLeft7());
        blockShapeList.add(BlockShape.blockShapeRight7());
        blockShapeList.add(BlockShape.blockShapeLeftZ());
        blockShapeList.add(BlockShape.blockShapeRightZ());
        blockShapeList.add(BlockShape.blockShapeBlock());
        blockShapeList.add(BlockShape.blockShapeT());
        blockShapeList.add(BlockShape.blockShapeLine());
        int randomIndex = RANDOM.nextInt(blockShapeList.size());
        int randomRotateCount = RANDOM.nextInt(4);
        BlockShape blockShape = blockShapeList.get(randomIndex);
        for (int i = 0; i < randomRotateCount; i++) {
            blockShape.blockShapeRotate();
        }
        // 将方块的最大Y轴置为-1
        Integer maxY = blockShape.getBlockList().stream().map(Block::getY).distinct().max(Integer::compareTo).orElse(0);
        int needMoveY = -1 - maxY;
        for (Block block : blockShape.getBlockList()) {
            block.setY(block.getY() + needMoveY);
        }
        return blockShape;
    }

    /**
     * 拷贝出新的方块 - 深拷贝
     */
    public BlockShape copyBlockShape() {
        return new BlockShape(this.rotate, this.blockList.stream()
                .map(block -> new Block(block.getX(), block.getY(), block.getColor())).collect(Collectors.toList()));
    }

    /**
     * 移动
     */
    public void blockShapeMove(int moveX, int moveY) {
        for (Block block : this.blockList) {
            block.setX(block.getX() + moveX);
            block.setY(block.getY() + moveY);
        }
    }

    /**
     * 旋转方块 (blockList 的第一个元素为原点)
     * Ax = Oy + Ox - By
     * Ay = Oy - Ox + Bx
     */
    public void blockShapeRotate() {
        if (!this.rotate) {
            return;
        }
        for (Block block : this.blockList) {
            int x = block.getX();
            int y = block.getY();
            block.setX(this.blockList.get(0).getY() + this.blockList.get(0).getX() - y);
            block.setY(this.blockList.get(0).getY() - this.blockList.get(0).getX() + x);
        }
    }
}
